﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Ngram
{
    class Model2
    {
        public string process(string input)
        {
            string[] wordUSArr = input.Split(' ');
            Dictionary<string, double> rs = null;
            Dictionary<string, double> rsTemp = null;

            if (wordUSArr.Length >= 1)
            {
                if (Data.P_One.ContainsKey(wordUSArr[0]))
                {
                    rs = Data.P_One[wordUSArr[0]];
                }
                else
                {
                    rs = new Dictionary<string, double>();
                    rs.Add(wordUSArr[0], Data.ThresholdNotFound);
                }
                if (wordUSArr.Length >= 2)
                {
                    rsTemp = new Dictionary<string, double>();
                    if (Data.P_One.ContainsKey(wordUSArr[1]))
                    {
                        foreach (KeyValuePair<string, double> r in rs)
                        {
                            string[] wordArr = r.Key.Split(' ');
                            string lastWord = wordArr[wordArr.Length - 1];
                            foreach (KeyValuePair<string, double> w in Data.P_One[wordUSArr[1]])
                            {
                                rsTemp.Add(r.Key + " " + w.Key, r.Value * S(lastWord + " " + w.Key));
                            }
                        }
                    }
                    else
                    {
                        foreach (KeyValuePair<string, double> r in rs)
                        {
                            rsTemp.Add(r.Key + " " + wordUSArr[1], r.Value * Data.ThresholdNotFound);
                        }
                    }
                    if (Data.AllowFilter)
                    {
                        rs = getRSForCount(rsTemp, Data.ThresholdFilter);
                    }
                    else
                        rs = rsTemp;
                    if (wordUSArr.Length >= 3)
                    {
                        for (int i = 1; i < wordUSArr.Length - 1; i++)
                        {
                            rsTemp = new Dictionary<string, double>();
                            if (Data.P_One.ContainsKey(wordUSArr[i+1]))
                            {
                                foreach (KeyValuePair<string, double> r in rs)
                                {
                                    string[] wordArr = r.Key.Split(' ');
                                    string lastWord = wordArr[wordArr.Length - 1];
                                    foreach (KeyValuePair<string, double> w in Data.P_One[wordUSArr[i+1]])
                                    {
                                        rsTemp.Add(r.Key + " " + w.Key, r.Value * S(lastWord + " " + w.Key));
                                    }
                                }
                            }
                            else
                            {
                                foreach (KeyValuePair<string, double> r in rs)
                                {
                                    rsTemp.Add(r.Key + " " + wordUSArr[i+1], r.Value * Data.ThresholdNotFound);
                                }
                            }
                            if (Data.AllowFilter)
                            {
                                rs = getRSForCount(rsTemp, Data.ThresholdFilter);
                            }
                            else
                                rs = rsTemp;
                        }
                    }
                }
            }

            return getRS(rs);
        }

        public double S(string w1w2)
        {
            if (Data.P_Two.ContainsKey(Utils.processUtils.ConvertToUnSign(w1w2)))
            {
                if (Data.P_Two[Utils.processUtils.ConvertToUnSign(w1w2)].ContainsKey(w1w2))
                {
                    return Data.P_Two[Utils.processUtils.ConvertToUnSign(w1w2)][w1w2];
                }
                else
                {
                    return Data.ThresholdNotFound;
                }
            }
            return Data.ThresholdNotFound;
        }
        public string getRS(Dictionary<string, double> rs)
        {
            try
            {
                double max = rs.Max(kvp => kvp.Value);
                return rs.Where(kvp => kvp.Value == max).Select(kvp => kvp.Key).First();
            }
            catch (Exception)
            {
                return null;
            }
        }
        public Dictionary<string, double> getRSForCount(Dictionary<string, double> RS, int count)
        {
            var items = from pair in RS
                        orderby pair.Value descending
                        select pair;
            Dictionary<string, double> rs = new Dictionary<string, double>();
            foreach (KeyValuePair<string, double> pair in items)
            {
                if (count == 0)
                    return rs;
                count--;
                rs.Add(pair.Key, pair.Value);
            }
            return rs;
        }
    }
}
